# Makefile
#
# Date: March 5, 2016
# Author: Brandon Perez
# Author: Jared Choi
#
# The top-level Makefile for the project, handles compilation for both the
# driver and the example application programs

# Include the user defined variables, if they specified them
-include config.mk

################################################################################
# Configuration
################################################################################

# Set the shell to BASH
SHELL = /bin/bash

# Allow the user to specify cross-compilation from the command line
CC = $(CROSS_COMPILE)gcc

# Standard gcc flags for compilation
GLOBAL_CFLAGS = -Wall -Wextra -Werror -std=gnu99 -g -O0

# The location where the compiled executables and driver will be stored
OUTPUT_DIR ?= outputs

# The location where the generated documentation files are stored
DOC_DIR = docs

################################################################################
# Targets
################################################################################

# None of the targets correspond to actual files
.PHONY: all docs clean cross_compiler_check help

# Compile the driver, library, and examples in release mode as the default
all: driver library examples

# Generate the doxygen documentation for library
docs: library_docs

# Include the specific targets for the examples, library, and driver (the
# includes must go here, so the default target is 'all')
include library/library.mk
include driver/driver.mk
include examples/examples.mk

# Make the specified output directory, if it doesn't exist
$(OUTPUT_DIR):
	@mkdir -p $(OUTPUT_DIR)

# Clean up all temporary files
clean: driver_clean examples_clean library_clean
	rm -rf $(OUTPUT_DIR)

# Check that the specified cross-compiler exists
cross_compiler_check:
ifdef CROSS_COMPILE
ifeq (,$(shell which $(CC)))
	@printf "Error: '$(CROSS_COMPILE)' is not a valid cross-compiler prefix. "
	@printf "'$(CC)' was not found in your path.\n"
	@exit 1
endif
endif

# Display a help message to the user
help:
	@printf "Usage:\n"
	@printf "\tmake [target] [variable] ...\n"
	@printf "\n"
	@printf "Targets:\n"
	@printf "\tall (default)\n"
	@printf "\t    The default target. Compiles all components.\n"
	@printf "\n"
	@printf "\tdocs\n"
	@printf "\t    Generates the Doxygen documentation all of the components.\n"
	@printf "\n"
	@printf "\tclean\n"
	@printf "\t    Cleans up all intermediate files generated by compilation\n"
	@printf "\t    of the driver and example programs.\n"
	@printf "\n"
	@printf "\tdriver\n"
	@printf "\t    Compiles the AXI DMA driver. The kernel object file can be\n"
	@printf "\t    found at '\$$(OUTPUT_DIR)/axidma.ko'.\n"
	@printf "\n"
	@printf "\tdriver_clean\n"
	@printf "\t    Cleans up files generated by the driver's compilation.\n"
	@printf "\n"
	@printf "\tlibrary\n"
	@printf "\t    Compiles the AXI DMA library. The shared library file can\n"
	@printf "\t    be found at '\$$(OUTPUT_DIR)/libaxidma.so'.\n"
	@printf "\n"
	@printf "\tlibrary_docs\n"
	@printf "\t    Generates the Doxygen documentation for the library as\n"
	@printf "\t    both as HTML and Latex. These can be found under 'docs'.\n"
	@printf "\t    Also, opens the HTML documentation in firefox.\n"
	@printf "\n"
	@printf "\tlibrary_clean\n"
	@printf "\t    Cleans up the files generated by compiling the library.\n"
	@printf "\n"
	@printf "\texamples, <example_name>\n"
	@printf "\t    Compiles the example programs or specific example program.\n"
	@printf "\t    The executable for a given example can be found at\n"
	@printf "\t    '\$$(OUTPUT_DIR)/<example name>'.\n"
	@printf "\n"
	@printf "\texamples_clean\n"
	@printf "\t    Cleans up files generated by compiling the examples.\n"
	@printf "\n"
	@printf "\thelp\n"
	@printf "\t    Display this help message.\n"
	@printf "\n"
	@printf "Variables:\n"
	@printf "\tThe variables can be specified either on the command line or\n"
	@printf "\tin 'config.mk'. See 'config_template.mk' for a template of the\n"
	@printf "\tMakefile configuration file and more detailed explanations.\n"
	@printf "\n"
	@printf "\tCROSS_COMPILE\n"
	@printf "\t    The prefix for the cross compiler to use for compilation.\n"
	@printf "\t    For example, \`arm-linux-gnueabi-\`. Not required; if left\n"
	@printf "\t    unspecified, then the system default compiler is used.\n"
	@printf "\n"
	@printf "\tARCH\n"
	@printf "\t    The architecture that the code is being compiled for.\n"
	@printf "\t    Only needed when cross-compiling the driver.\n"
	@printf "\n"
	@printf "\tKBUILD_DIR\n"
	@printf "\t    The path to the kernel source tree to build the driver\n"
	@printf "\t    against. Required when cross-compiling the driver.\n"
	@printf "\t    Otherwise, may be left unspecified. If it is, the system\n"
	@printf "\t    default is used.\n"
	@printf "\n"
	@printf "\tOUTPUT_DIR\n"
	@printf "\t    The path where the generated code files (both the kernel \n"
	@printf "\t    object file and executables) will be stored. The default \n"
	@printf "\t    is the "outputs" in the top-level directory.\n"
	@printf "\n"
	@printf "\tXILINX_DMA_INCLUDE_PATH_FIXUP\n"
	@printf "\t    Specifies to fix and issue with the location of the header\n"
	@printf "\t    file 'xilinx_dma.h' in the kernel you're compiling against\n"
	@printf "\t    Specify if you see an include error when compiling.\n"
	@printf "\n"
	@printf "Examples:\n"
	@printf "\tmake\n"
	@printf "\tmake CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm "
	@printf "KBUILD_DIR=/home/kernels/linux/ driver\n"
	@printf "\tmake CROSS_COMPILE=arm-linux-gnueabihf- OUTPUT_DIR=outputs "
	@printf "examples\n"
	@printf "\tmake axidma_benchmark\n"
	@printf "\tmake OUTPUT_DIR=outputs clean\n"
